-- -- Copyright 2014 Alessandro Gerlinger Romero -- -- This file is part of Hybrid fUML. -- -- Hybrid fUML is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation, either version 3 of the License, or -- (at your option) any later version. -- -- Hybrid fUML is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with Hybrid fUML. If not, see . -- ------------------------------------------------------------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------------------------------------------------------------ -- CONTROLNODES ------------------------------------------------------------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------------------------------------------------------------ -- APPROACH -- SEMANTICVISITOR NOT RELATED WITH VALUE ARE IMPLEMENTED AS RULES -- THERE ARE NO DATA FOR ...Activation -- RULES DEFINITION ------------------------------------------------------------------------------------------------------------------------------------------------------------ -- CLASS FUML_Semantics_Activities_IntermediateActivities_InitialNodeActivation -- FUML_Syntax_Activities_IntermediateActivities_InitialNode -- operatio_InitialNodeActivation_fire :: FUML_Semantics_Activities_IntermediateActivities_ActivityNodeActivation -> Rule () operatio_InitialNodeActivation_fire (vl,ino) = skip ------------------------------------------------------------------------------------------------------------------------------------------------------------ -- CLASS FUML_Semantics_Activities_IntermediateActivities_MergeNodeActivation -- FUML_Syntax_Activities_IntermediateActivities_MergeNode -- operatio_MergeNodeActivation_fire :: FUML_Semantics_Activities_IntermediateActivities_ActivityNodeActivation -> Rule () operatio_MergeNodeActivation_fire (vl, mn) = skip ------------------------------------------------------------------------------------------------------------------------------------------------------------ -- CLASS FUML_Semantics_Activities_IntermediateActivities_FlowFinalNodeActivation -- FUML_Syntax_Activities_IntermediateActivities_FlowFinalNode -- operatio_FlowFinalNodeActivation_fire :: FUML_Semantics_Activities_IntermediateActivities_ActivityNodeActivation -> Rule () operatio_FlowFinalNodeActivation_fire (vl, fn) = let fnb = (function_ActivityNode_type(fn) == FUML_Syntax_Activities_IntermediateActivities_FlowFinalNode) in let acfnb = function_fUML_activityHasNode (function_fUML_activity vl) fn in -- checking -- it is a FlowFinalNode, and is for the classifier from the value if fnb && acfnb then -- checking -- has token if function_ActivityNodeActivation_isReady (vl,fn) then -- remove token function_ActivityNodeActivation_heldTokens(vl,fn) := {} else skip else skip ------------------------------------------------------------------------------------------------------------------------------------------------------------ -- CLASS FUML_Semantics_Activities_IntermediateActivities_ForkNodeActivation -- FUML_Syntax_Activities_IntermediateActivities_ForkNode -- operatio_ForkNodeActivation_fire :: FUML_Semantics_Activities_IntermediateActivities_ActivityNodeActivation -> Rule () operatio_ForkNodeActivation_fire (vl, fn) = let fnb = (function_ActivityNode_type(fn) == FUML_Syntax_Activities_IntermediateActivities_ForkNode) in let acfnb = function_fUML_activityHasNode (function_fUML_activity vl) fn in -- checking -- it is a FlowFinalNode, and is for the classifier from the value if fnb && acfnb then -- checking -- has token if function_ActivityNodeActivation_isReady (vl,fn) then let t = one $ function_ActivityNodeActivation_heldTokens(vl,fn) in let tt = function_Token_type t in do -- for all edges forall e <- (expr2list $ function_ActivityNode_outgoing(fn)) do -- create an offer create off do -- with new token nt <- (rule_FUML_Semantics_Activities_IntermediateActivities_Token_create tt) function_Token_ObjectToken_value(nt):= function_Token_ObjectToken_value(t) function_Offer_offeredTokens(off) := {nt} function_ActivityEdgeInstance_offers(vl,e) := {off} else skip else skip ------------------------------------------------------------------------------------------------------------------------------------------------------------ -- CLASS FUML_Semantics_Activities_IntermediateActivities_DecisionNodeActivation -- FUML_Syntax_Activities_IntermediateActivities_DecisionNode -- operatio_DecisionNodeActivation_fire :: FUML_Semantics_Activities_IntermediateActivities_ActivityNodeActivation -> Rule () operatio_DecisionNodeActivation_fire (vl, dn) = let dnb = (function_ActivityNode_type(dn) == FUML_Syntax_Activities_IntermediateActivities_DecisionNode) in let acdnb = function_fUML_activityHasNode (function_fUML_activity vl) dn in -- checking -- it is a FlowFinalNode, and is for the classifier from the value if dnb && acdnb then -- checking -- has token if function_ActivityNodeActivation_isReady (vl,dn) then -- has decisioninput flow if dei /= FUML_Syntax_Activities_IntermediateActivities_ActivityEdgeEmpty then -- offer for edges that has the same value than the objectnode source a control token do -- evaluating edges evs <- rforall e <- es do ev <- operatio_Executor_evaluate (function_Locus_executor (function_Value_ExtensionalValue_locus vl)) (function_ActivityEdge_guard e) result(e, ev) -- using a support function to overcome state transfering function_fUML_decisionNodeSupport(vl, dn) := evs `seq` do if length otv /= 1 then error("operatio_DecisionNodeActivation_fire The DecisionNode is using DecisionInputFlow, however, there is no unique object to be compared. name: " ++ show dn ++ show otv) else skip forall (e, ev) <- (function_fUML_decisionNodeSupport(vl, dn)) do if ev `operatio_Value_equals` div then create off do nct <- (rule_FUML_Semantics_Activities_IntermediateActivities_Token_create FUML_Semantics_Activities_IntermediateActivities_ControlToken) function_Offer_offeredTokens(off) := {nct} function_ActivityEdgeInstance_offers(vl,e) := {off} else skip function_fUML_decisionNodeSupport(vl, dn) := [] `seq` -- check if it has generated at least one offer if length hasGenerattedOffer > 0 then skip else -- otherwise to one (only one) that has guard as true if length otherwis == 1 then -- offers a control token for the otherwise edge create off do nct <- (rule_FUML_Semantics_Activities_IntermediateActivities_Token_create FUML_Semantics_Activities_IntermediateActivities_ControlToken) function_Offer_offeredTokens(off) := {nct} function_ActivityEdgeInstance_offers(vl,otherwisNode) := {off} else error("operatio_DecisionNodeActivation_fire The DecisionNode is using DecisionInputFlow, however, none of the guards matchs and there is no deterministic applicable otherwise(GUARD Boolean:True). name: " ++ show dn) else if di == FUML_Syntax_Classes_Kernel_ClassifierEmpty then -- offer for all edges forall e <- es do -- create offer create off do -- with new token nct <- (rule_FUML_Semantics_Activities_IntermediateActivities_Token_create FUML_Semantics_Activities_IntermediateActivities_ControlToken) function_Offer_offeredTokens(off) := {nct} function_ActivityEdgeInstance_offers(vl,e) := {off} else error("operatio_DecisionNodeActivation_fire The DecisionNode is using DecisionInput. This is not supported. " ++ show dn) else skip else skip where es = expr2list (function_ActivityNode_outgoing dn) -- decision input flow dei = function_ActivityNode_DecisionNode_decisionInputFlow dn -- decision input di = function_ActivityNode_DecisionNode_decisionInput dn -- -- tokens otv = filter (\t -> function_Token_type(t) == FUML_Semantics_Activities_IntermediateActivities_ObjectToken) ( expr2list $ function_ActivityNodeActivation_heldTokens (vl,dn)) div = if length otv /= 1 then FUML_Semantics_Classes_Kernel_ValueEmpty else function_Token_ObjectToken_value $ head otv -- otherwise otherwis = filter (\e -> function_ActivityEdge_guard(e) /= FUML_Syntax_Classes_Kernel_ValueSpecificationEmpty && function_ValueSpecification_type(function_ActivityEdge_guard e) == FUML_Syntax_Classes_Kernel_LiteralBoolean && function_ValueSpecification_LiteralBoolean_value(function_ActivityEdge_guard e) ) es otherwisNode = head otherwis -- has generated at least one offer hasGenerattedOffer = filter (\e -> function_ActivityEdgeInstance_offers(vl,e) /= {}) es -- -- function to support evaluation and comparison in differents steps function_fUML_decisionNodeSupport :: Dynamic( FUML_Semantics_Activities_IntermediateActivities_ActivityNodeActivation -> [(FUML_Syntax_Activities_IntermediateActivities_ActivityEdge, FUML_Semantics_Classes_Kernel_Value)] ) function_fUML_decisionNodeSupport = initAssocs' "function_fUML_decisionNodeSupport" [] asmLt (==) [] ------------------------------------------------------------------------------------------------------------------------------------------------------------ -- HELP FUNCTIONS -- checks if a node is part of an activity function_fUML_activityHasNode :: FUML_Syntax_Classes_Kernel_Classifier -> FUML_Syntax_Activities_IntermediateActivities_ActivityNode -> Bool function_fUML_activityHasNode ac n = function_Activity_node(ac) `intersect` {n} /= {} -- retrieves the activity for a given activityexecution function_fUML_activity :: FUML_Semantics_Classes_Kernel_Value -> FUML_Syntax_Classes_Kernel_Classifier function_fUML_activity vl = if function_Value_type(vl) == FUML_Semantics_Activities_IntermediateActivities_ActivityExecution then function_fUML_oneClassifierType vl else FUML_Syntax_Classes_Kernel_ClassifierEmpty